;;	isr.asm
;;	Este archivo posee todas las rutinas para la atencion de las interrupciones

;importo algunos macros utiles
%include "isr-def.mac"

;exporto algunas rutinas para que puedan ser utilizadas de afuer
global dummy_isr
global timer_isr
;exporto la variable que cuenta los ticks
global timer_ticks
global task_isr
global task_isr_ret
global serial_isr
global hdd_isr_14
global hdd_isr_15
global spurious_isr
global keyboard_isr
global page_fault_isr

;importo algunas funciones
extern debug_kernelpanic
extern loader_switchto
extern sched_tick
extern serial_isr_c
extern hdd_isr_c
extern keyboard_handler
extern mm_copy_page_fault

;variable global para contar los ticks del clock
timer_ticks:
	dd 0x00

;rutina de atencion vacia
dummy_isr:
	;desactivo las int
	cli
	;paro el micro
	hlt
	;me cuelgo
	jmp $

;rutina por defecto de atencion del tick que incremente su contador
timer_isr:
	;desactivo las int
	cli
	;guardo eax y ds
	push eax
	push ds
	;seteo el segmento de datos en anillo 0 para poder escribiren timer_ticks (porque esta en memoria restringida) 
	ISR_ENTORNO ax
	;incremento el contador de ticks	
	add dword [timer_ticks], 1
	;activo las interrupciones	
	FIN_DE_INTERRUPCION
	;restauro los registros	
	pop ds
	pop eax
	;me voy :)
	iret

;rutinas de atencion de interrupciones del micro
DEBUG_ISR_SIN_EC 00
DEBUG_ISR_SIN_EC 01
DEBUG_ISR_SIN_EC 02
DEBUG_ISR_SIN_EC 03
DEBUG_ISR_SIN_EC 04
DEBUG_ISR_SIN_EC 05
DEBUG_ISR_SIN_EC 06
DEBUG_ISR_SIN_EC 07
DEBUG_ISR_CON_EC 08
DEBUG_ISR_SIN_EC 09
DEBUG_ISR_CON_EC 0A
DEBUG_ISR_CON_EC 0B
DEBUG_ISR_CON_EC 0C
DEBUG_ISR_CON_EC 0D ; GP
DEBUG_ISR_CON_EC 0E ; Page
; no hay 15 0xf
DEBUG_ISR_SIN_EC 10
DEBUG_ISR_CON_EC 11
DEBUG_ISR_SIN_EC 12
DEBUG_ISR_SIN_EC 13
;rutinas de atencion de interrupciones del PIC
DEBUG_ISR_SIN_EC 20
DEBUG_ISR_SIN_EC 21
DEBUG_ISR_SIN_EC 22
DEBUG_ISR_SIN_EC 23
DEBUG_ISR_SIN_EC 24
DEBUG_ISR_SIN_EC 25
DEBUG_ISR_SIN_EC 26
DEBUG_ISR_SIN_EC 27
DEBUG_ISR_SIN_EC 28
DEBUG_ISR_SIN_EC 29
DEBUG_ISR_SIN_EC 2A
DEBUG_ISR_SIN_EC 2B
DEBUG_ISR_SIN_EC 2C
DEBUG_ISR_SIN_EC 2D
DEBUG_ISR_SIN_EC 2E
DEBUG_ISR_SIN_EC 2F
;rutina de atencion de interrupcion para las syscall
DEBUG_ISR_SIN_EC 30

;rutina de atencion de interrupcion para cambiar de tarea
task_isr:
	;deshabilito las interrupciones
	cli
	;resguardo todos los registros
	PUSHALL
	;seteo los segmentos en anillo 0 para poder acceder a memoria protegida
	mov ax, 0x10 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	;incremente el timer tick
	add dword [timer_ticks], 1
	;obtengo el pid de la tarea a quien le corresponde el cpu en eax;
	call sched_tick
	;apilo el pid para pasarselo al loader
	push eax;
	;llamo al loader para cambiar de tarea si es necesario
	;xchg bx, bx
	call loader_switchto
task_isr_ret:
	pop eax;
	;habilito las interrupciones
	FIN_DE_INTERRUPCION 
	;restauro todos los registros
	POPALL		
	;salgo de la interrupcion
	iret
	
;rutina de atencion del puerto serie
serial_isr:
	;deshabilito las interrupciones
	cli
	;xchg bx,bx
	;resguardo todos los registros
	PUSHALL
	;seteo los segmentos en anillo 0 para poder acceder a memoria protegida
	mov ax, 0x10 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	call serial_isr_c
	;habilito las interrupciones
	FIN_DE_INTERRUPCION 
	;restauro todos los registros
	POPALL		
	;salgo de la interrupcion
	iret

hdd_isr_14:
	;deshabilito las interrupciones
	cli
	;xchg bx,bx
	;resguardo todos los registros
	PUSHALL
	;seteo los segmentos en anillo 0 para poder acceder a memoria protegida
	mov ax, 0x10 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	push dword 0
	call hdd_isr_c
	add esp, 4
	;habilito las interrupciones
	FIN_DE_INTERRUPCION 
	mov al, 0x20
	out 0xA0, al
	;restauro todos los registros
	POPALL		
	;salgo de la interrupcion
	iret

hdd_isr_15:
	;deshabilito las interrupciones
	cli
	;xchg bx,bx
	;resguardo todos los registros
	PUSHALL
	;seteo los segmentos en anillo 0 para poder acceder a memoria protegida
	mov ax, 0x10 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	push dword 1
	call hdd_isr_c
	add esp, 4
	;habilito las interrupciones
	FIN_DE_INTERRUPCION 
	mov al, 0x20
	out 0xA0, al
	;restauro todos los registros
	POPALL		
	;salgo de la interrupcion
	iret

spurious_isr:
	cli
	;xchg bx, bx
	push eax
	mov eax, 0x0B
	out 0x20, al
	in al, 0x20
	and al, 0x80
	jz spurious_isr_end
	
	FIN_DE_INTERRUPCION 
spurious_isr_end:	
	pop eax
	iret

keyboard_isr:
	cli
	PUSHALL
	;seteo los segmentos en anillo 0 para poder acceder a memoria protegida
	mov ax, 0x10 
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov eax, 0
	in al, 60h 
	push eax
	call keyboard_handler
	pop eax
	FIN_DE_INTERRUPCION 	
	POPALL
	iret

page_fault_isr:
	push dword 0x0e ; Int Code
	pushad
	push ss
	push ds
	push es
	push fs
	push gs
	
	ISR_ENTORNO ax
	
	push esp
	push ebp
	call mm_copy_page_fault
	add esp, 8
	
	pop gs
	pop fs
	pop es
	pop ds
	pop ss
	popad
	add esp, 8  ;Error code
	iret
